package com.flyiu.data.idempotent.handler;

import java.lang.reflect.Type;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;

import com.flyiu.data.idempotent.exception.IdempotentException;
import com.flyiu.data.idempotent.model.DefaultIdempotentEntity;
import com.flyiu.data.idempotent.repository.FixLengCacheRepository;
import com.flyiu.foundational.asserts.Assert;
import com.google.gson.Gson;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * <p>
 * 默认幂等拦截器，需自行继承IdempotentHandler，并在Idempotent.idempotentHandler中指定
 * 通过business_variables构建幂性，保存出入参的方式处理。
 * 
 * 可能存在的问题，afrerResponse
 *
 * @author flyiu@flyiu.com
 * @version $Id: DefaultIempotentHandler.java, v 0.1 2018年6月30日 下午6:10:21 flyiu Exp $
 */
@Slf4j
//@ConditionalOnMissingBean(IdempotentHandler.class)
//@Component
public class DefaultIempotentHandler extends IdempotentHandler<DefaultIdempotentEntity> {

    public DefaultIempotentHandler() {
        System.out.println("DefaultIempotentHandler 寖化");
    }

    /** 默认幂等性属性保存Mapper */
    @Autowired
    private FixLengCacheRepository idempotentRepository;

    /** 使用GSON，可处理泛型问题 */
    private static final Gson      gson       = new Gson();

    private static final String    SPLIT_CHAR = "X@X";

    /**
     * 对象转Json String
     * 
     * @param arg
     * @return
     */
    private static String toJson(Object arg) {
        if (arg != null) {
            String context = "";
            context = gson.toJson(arg);
            return context;
        }
        return "";
    }

    /**
     * 对象数组转Json串，对象中以 SPLIT_CHAR 分割
     * 
     * @param args
     * @return
     */
    private static String toJson(Object[] args) {
        if (args != null) {
            StringBuffer context = new StringBuffer();
            for (Object arg : args) {
                context.append(gson.toJson(arg, arg.getClass()) + SPLIT_CHAR);
            }
            return context.toString();
        }
        return "";
    }

    @Override
    protected Object before(Object[] args, String hashCode) {
        // DefaultIdempotentEntity DefaultIdempotentEntity = new DefaultIdempotentEntity();
        // // DefaultIdempotentEntity.setContext(toJson(args));
        // DefaultIdempotentEntity.setHash(hashCode);
        // DefaultIdempotentEntity.setIdemValue(idemValuesThreadLocal.get());
        // idempotentRepository.save(DefaultIdempotentEntity);
        // DefaultIdempotentEntityThreadLocal.set(DefaultIdempotentEntity);
        // return DefaultIdempotentEntity;
        return null;
    }

    @Override
    protected void afterResponse(Object responseObj) {
        DefaultIdempotentEntity defaultIdempotentEntity = idempotentRepository.findByKey(getIdempotentKey());
        defaultIdempotentEntity.setState("COMMIT");
        idempotentRepository.save(defaultIdempotentEntity);
        super.afterResponse(responseObj);
    }

    @Override
    protected Object buildDuplicateResponse(DefaultIdempotentEntity idempotentEntity,Type reponseType) {
        DefaultIdempotentEntity recod = idempotentRepository.findByKey(idempotentEntity.getKey());
        if (recod != null) {
            Assert.assertNotTrue(()-> new IdempotentException("010005001100", "请求正在处理中,请稍候重试"), StringUtils.equals(recod.getState(), "I"));
            Assert.assertEquals(()->new IdempotentException("010004031100", "请求已存在,且当次请求与之前参数不匹配"), idempotentEntity.getHash(), recod.getHash());
            Assert.assertNotTrue(()->new IdempotentException("010005001101", "幂等失败，请检查业务结果"), StringUtils.isEmpty(recod.getResponse()));
            return gson.fromJson(recod.getResponse(), reponseType);
        }
        return null;
    }

    public boolean tryAcquire(DefaultIdempotentEntity idempotentEntity) {
//        DefaultIdempotentEntity DefaultIdempotentEntity = new DefaultIdempotentEntity();
        try {
            idempotentRepository.save(idempotentEntity);
            return true;
        } catch (Exception e) {
            log.error("尝试征用幂等 key {} 失败 ", idempotentEntity.getKey());
        }
        return false;
    }

}
